<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // Promise: ES6新出的一个对象, 用于管理异步任务, 解决回调地狱问题
        // 怎么解决: 用的是Promise的链式调用的特征
        // 1. 复习-基础用法
        // 创建Promise对象
        // let p = new Promise((resolve, reject) => {
        //     // 异步任务-ajax/定时器计时器
        //     setTimeout(() => {
        //         // resolve('成功')
        //         reject('失败')
        //     }, 2000) // 2秒好比是ajax需要请求+响应总耗费时间(模拟)
        // })
        // 如何拿到Promise对象里成功/失败的结果?
        // resolve() -> .then()里函数体代码执行
        // reject() ->  .catch()里函数体代码执行
        // p.then(res => {
        //     console.log(res);
        // })
        // p.catch(err => {
        //     console.log(err);
        // })

        // 高级用法1:
        // 口诀: Promise对象.then() 在原地会有一个返回值, 是一个"全新的Promise对象"
        // let pB = p.then()
        // console.log(pB === p); // false

        // 高级语法2:
        // 口诀: Promise对象.catch() 在原地会有一个返回值, 是一个"全新的Promise对象"
        // 链式调用: 每个函数里返回同样的一个对象, 继续点调用内部的其他方法, 一直点下去就是链式调用
        // let pB = p.then().catch()
        // console.log(pB === p);

        // 高级用法3:
        // 口诀: then()里函数体里的return, 返回给下一个Promise对象使用
        // 情况1: return的是非Promise对象
        // let pB = p.then(res => { // res : '成功'
        //     return 1000 // 特殊: return给pB(下一个Promise对象的then里使用)
        // })

        // pB.then(result => {
        //     console.log(result); // 1000
        // })

        // 情况2: return的是一个新的Promise对象呢, 替换then()函数默认在原地返回的那个"全新Promise对象"
        // 下一个then里拿到的是return的这个Promise对象里resolve的结果
        // let pB = p.then(res => { // res : '成功'
        //     console.log(res);
        //     return new Promise((resolve, reject) => {
        //         setTimeout(() => {
        //             resolve('第二次成功值')
        //         }, 3000)
        //     })
        // })

        // pB.then(result => {
        //     console.log(result); // 第二次成功值
        // })

        // 高级用法4: catch()里return会返回到, 下一个Promise对象的then里使用
        // 总结: 无论then/catch里()里函数体的return, 都会返回给下一个Promise的"then"里
        // let pB = p.catch(err => {
        //     console.log(err);
        //     return 1000;
        // })

        // pB.then(result => {
        //     console.log(result); // 1000
        // })


        // awaitTo技术
        // 为什么: 因为await 只能默认取代then函数, 只能拿到then的结果
        // 如果await后面Promise内报错, 我们需要使用try+catch来进行捕获
        // 解决: 我想把try+catch优化掉, 让await可以提取到成功和失败的结果
        // 例如:
        function myAxios() {
            let pA = new Promise((resolve, reject) => {
                setTimeout(() => {
                    reject('失败')
                }, 2000)
            })
            return pA
        }
        let pA = myAxios() // 模拟axios()函数, 以前await pA拿结果, 但是现在中间处理后, 用await 取pB结果(只能取成功)

        let pB = pA.then(res => {
            return [null, res]
        }).catch(err => {
            return [err, null] // 会返回给pB的then使用(pA的错误信息中转下去)
        })
        
        async function myFn(){ // 逻辑页面拿处理后的Promise对象里结果(有成功/失败)
            const [err, res] = await pB // await还是取代pB的then
            if (err) console.error(err)
            else console.log(res)
            // 1个变量位置无法区分是成功值/失败值, 那么我在中转的地方传出一个数组
            // 数组的第一个位置错误信息, 第二个位置正确的信息
        }
        myFn()

        
    </script>
</body>

</html>